package com.ai.module.chat.util.aliyun;

/**
 * @author: MrHe
 * @create: 2023-11-30 22:03
 * @description:
 **/

import com.ai.module.chat.common.domain.bo.AliUploadBo;
import com.ai.module.chat.common.domain.vo.AliFileVo;
import com.ai.module.chat.common.domain.vo.RiskReason;
import com.ai.module.chat.config.properties.AliyunProperty;
import com.ai.module.chat.util.DateUtils;
import com.ai.module.chat.util.FileUtils;
import com.ai.module.chat.util.SpringUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.green20220302.Client;
import com.aliyun.green20220302.models.*;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class AliyunUtil {

    public static AliyunProperty aliyunProperty =
           // null;
            SpringUtils.getClazz(AliyunProperty.class);

    public static RiskReason getRiskReason(String askMessage) {
        if (StringUtils.isBlank(askMessage)){
            return new RiskReason();
        }
        String regex = "(?i)(chatgpt|gpt|openai)";
        // 检查字符串是否匹配
        boolean containsSensitiveWords = askMessage.matches(".*" + regex + ".*");
        if (containsSensitiveWords){
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(askMessage);
            List<String> riskList = new ArrayList<>();
            // 循环查找匹配项
            while (matcher.find()) {
                String group = matcher.group();
                riskList.add(group);
            }
            RiskReason riskReason = new RiskReason();
            riskReason.setSuccess(false);
            riskReason.setRiskTips(riskList);
            return riskReason;
        }
        CompletableFuture<RiskReason> future = textModerationAsync(askMessage);
        RiskReason riskReason = null;
        try {
            riskReason = future.get();
            List<String> riskTips = riskReason.getRiskTips();
            if (!CollectionUtils.isEmpty(riskTips)){
                riskReason.setSuccess(false);
                log.error("敏感词校验失败,敏感词为 [{}]",JSONObject.toJSONString(riskTips));
            }
        } catch ( Exception e) {
            e.printStackTrace();
            log.error("敏感词校验失败,异常信息  [{}]",e.getMessage());
            riskReason= new RiskReason();
        }
        return riskReason;
    }
    @Deprecated
    public static CompletableFuture<RiskReason> textModerationAsync(String content) {
        try {
            return CompletableFuture.completedFuture(textModeration(content));

        } catch (Exception ex) {
            ex.printStackTrace();
            log.error("文本审核接口错误,ex{},content{}", ex.getMessage(), content);
            return CompletableFuture.completedFuture(new RiskReason());
        }

    }

    private static Client getCipClient() throws Exception {
        AliyunProperty aliyunProperty = getAliyunOssCip();
        String accessKeySecret = aliyunProperty.getAccessKeySecret();
        String accessKeyId = aliyunProperty.getAccessKeyId();
        Config cipConfig = new Config();
        cipConfig.setAccessKeyId(accessKeyId);
        cipConfig.setAccessKeySecret(accessKeySecret);
        cipConfig.setRegionId(aliyunProperty.getCipRegionId());
        cipConfig.setEndpoint(aliyunProperty.getCipChinaEndPoint());
        return new Client(cipConfig);
    }

    private static OSS getOssClient() {
        AliyunProperty aliyunProperty = getAliyunOssCip();
        String accessKeySecret = aliyunProperty.getAccessKeySecret();
        String accessKeyId = aliyunProperty.getAccessKeyId();
        CredentialsProvider ossCredentialsProvider =
                new DefaultCredentialProvider(accessKeyId, accessKeySecret);
        return new OSSClientBuilder().build(aliyunProperty.getOssChinaEndPoint(), ossCredentialsProvider);
    }


    public static void createOSSBucket(String bucketName) {
        OSS ossClient = getOssClient();
        try {
            // 创建OSS存储空间。
            CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
            ossClient.createBucket(createBucketRequest);
        } catch (OSSException | ClientException e) {
            e.printStackTrace();
            log.error("阿里云创建bucket失败message [{}]", e.getMessage());
        }
    }

    public static String uploadOSSFile(
            File file,
            AliUploadBo aliUploadBo,
            boolean isAiDraw
    ) {
        OSS ossClient = getOssClient();
        try {
            //AliyunOssCip aliyunOssCip = getAliyunOssCip();
            String ossBucketName = aliyunProperty.getOssBucketName();
            String objectName = aliUploadBo.getProjectName();
            ZoneId zoneId = ZoneId.systemDefault();
            LocalDateTime localDateTime = aliUploadBo.getExpireDate();
            ZonedDateTime zdt = localDateTime.atZone(zoneId);

            Date expireDate = Date.from(zdt.toInstant());

            PutObjectRequest putObjectRequest = new PutObjectRequest(ossBucketName, objectName, file);
            ossClient.putObject(putObjectRequest);

            String imageUrl = ossClient.generatePresignedUrl(ossBucketName, objectName,expireDate ).toString();

            if (file.exists()){
                file.delete();
            }
            return imageUrl;

        } catch (OSSException | ClientException e) {
            e.printStackTrace();
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static String uploadOSSFile(
            File file,
            AliUploadBo aliUploadBo
    ) throws Exception {
        long start = System.currentTimeMillis();
        OSS ossClient = getOssClient();
        try {
            //AliyunOssCip aliyunOssCip = getAliyunOssCip();
            String ossBucketName = aliyunProperty.getOssBucketName();
            String objectName = aliUploadBo.getProjectName();
            ZoneId zoneId = ZoneId.systemDefault();
            LocalDateTime localDateTime = aliUploadBo.getExpireDate();
            ZonedDateTime zdt = localDateTime.atZone(zoneId);

            Date expireDate = Date.from(zdt.toInstant());

            PutObjectRequest putObjectRequest = new PutObjectRequest(ossBucketName, objectName, file);
            ossClient.putObject(putObjectRequest);

            String imageUrl = ossClient.generatePresignedUrl(ossBucketName, objectName,expireDate ).toString();

            if (file.exists()){
                file.delete();
            }
            log.info("阿里云文件上传耗时 [{}]  ", System.currentTimeMillis() - start);

            return imageUrl;

        } catch (Exception e) {
            e.printStackTrace();
           throw e;
        }
    }

    public static String uploadOSSFileNoDelete(String objectName,
                                               File file,
                                               Date expireDate,
                                               String ossBucketName
    ) {
        OSS ossClient = getOssClient();
        try {
            AliyunProperty aliyunProperty = getAliyunOssCip();
            PutObjectRequest putObjectRequest = new PutObjectRequest(ossBucketName, objectName, file);
            ossClient.putObject(putObjectRequest);

            return ossClient.generatePresignedUrl(ossBucketName, objectName, expireDate).toString();


        } catch (OSSException | ClientException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String downloadOSSFile(String objectName) {
        OSS ossClient = getOssClient();
        AliyunProperty aliyunProperty = getAliyunOssCip();
        try {
            OSSObject ossObject = ossClient.getObject(aliyunProperty.getOssBucketName(), objectName);
            InputStream content = ossObject.getObjectContent();
            StringBuilder contentBuilder = new StringBuilder();

            if (content != null) {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(content))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        contentBuilder.append(line);
                        contentBuilder.append("\n");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    content.close();

                }
            }

            return contentBuilder.toString();
        } catch (OSSException | ClientException | IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Nullable
    public static AliFileVo uploadImageAndGetUrl(String url,
                                                 String fileName) {
        long start = System.currentTimeMillis();
        log.info("阿里云文件上传开始, 原始url [{}], file name[{}] current Time [{}]",url,fileName, DateUtils.getCurrentTime());

        Boolean scale = false;
        AliFileVo aliFileVo = new AliFileVo();
        AliUploadBo uploadBo = new AliUploadBo();
        try {

            aliFileVo.setOriginalFilePath(url);
            File tempFile = File.createTempFile(fileName, ".jpg");
            FileUtils.writeFileByUrl(url, tempFile);
            AliyunProperty aliyunProperty = getAliyunOssCip();
            Date expireTime = new Date(System.currentTimeMillis() + DateUtils.HALF_YEAR);
            // 文件上传 阿里云
            String filePath = AliyunUtil.uploadOSSFileNoDelete(String.format("%s.jpg", fileName), tempFile, expireTime, aliyunProperty.getOssBucketName());
            aliFileVo.setFilePath(filePath);
            aliFileVo.setScaleFilePath(filePath);
            aliFileVo.setExpireTime(LocalDateTime.now().plusMonths(6));
            if (scale) {
                File scaleFile = File.createTempFile(fileName + "_scale", ".jpg");
                dealScaleFile(tempFile, scaleFile);
                String completeFileName = String.format("%s.jpg", fileName);
                uploadBo.setProjectName(completeFileName);
                String scaleFilePath = AliyunUtil.uploadOSSFile(scaleFile, uploadBo,true);
                aliFileVo.setScaleFilePath(scaleFilePath);
                aliFileVo.setProjectName(completeFileName);
            }
            if (tempFile.exists()) {
                tempFile.delete();
            }
            log.info("阿里云文件上传耗时[{}] aliFileVo [{}]", System.currentTimeMillis() - start, aliFileVo);
            return aliFileVo;
        } catch (Exception ex) {
            ex.printStackTrace();
            log.error("阿里云文件上传失败: ex[{}] ,url[{}] ,fileName[{}]", ex.getMessage(), url, fileName);
            return aliFileVo;
        }


    }

    public static String generatePresignedURL(String objectName, long expirationTimeMillis) {
        OSS ossClient = getOssClient();
        AliyunProperty aliyunProperty = getAliyunOssCip();
        try {
            Date expiration = new Date(System.currentTimeMillis() + expirationTimeMillis);
            URL url = ossClient.generatePresignedUrl(aliyunProperty.getOssBucketName(), objectName, expiration);
            return url.toString();
        } catch (OSSException | ClientException e) {
            e.printStackTrace();
            return null;
        }
    }
    public static String generatePresignedURLT(String objectName,
                                               long expirationTimeMillis,
                                               OSS ossClient) {

        AliyunProperty aliyunProperty = getAliyunOssCip();
        try {
            Date expiration = new Date(System.currentTimeMillis() + expirationTimeMillis);
            URL url = ossClient.generatePresignedUrl(aliyunProperty.getOssBucketName(), objectName, expiration);
            return url.toString();
        } catch (OSSException | ClientException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static RiskReason textModeration(String content) throws Exception {
        if (content.length() >= 500) {
            content = content.substring(0, 500);
        }
        RiskReason riskReason = new RiskReason();
        Client cipClient = getCipClient();
        try {
            JSONObject serviceParameters = new JSONObject();
            serviceParameters.put("content", content);
            TextModerationRequest textModerationRequest = new TextModerationRequest();
            textModerationRequest.setService("ai_art_detection");
            textModerationRequest.setServiceParameters(serviceParameters.toJSONString());
            RuntimeOptions runtime = new RuntimeOptions();
            runtime.readTimeout = 10000;
            runtime.connectTimeout = 10000;
            TextModerationResponse response = cipClient.textModerationWithOptions(textModerationRequest, runtime);

            if (response != null) {
                if (response.getStatusCode() == 200) {
                    TextModerationResponseBody result = response.getBody();
                    Integer code = result.getCode();
                    if (code != null && code == 200) {
                        TextModerationResponseBody.TextModerationResponseBodyData data = result.getData();
                        String message = "Labels: " + data.getLabels() + "\nReason: " + data.getReason();
                        riskReason.setStatusCode(response.getStatusCode());
                        if (StringUtils.isBlank(data.getLabels()) &&
                                StringUtils.isBlank(data.getReason())) {
                            riskReason.setSuccess(true);
                            return riskReason;
                        }
                        JSONObject json = JSONObject.parse(data.getReason());
                        riskReason.setRiskWords(json.getString("riskWords").split(",")[0]);
                        riskReason.setRiskTips(Lists.newArrayList(data.getLabels()));
                        riskReason.setMessage(message);
                        return riskReason;
                    } else {
                        String message = "Text moderation not successful. Code: " + code;
                        riskReason.setStatusCode(response.getStatusCode());
                        riskReason.setMessage(message);
                        log.error("文字审核失败 {}", message);
                        return riskReason;
                    }
                } else {
                    riskReason.setStatusCode(response.getStatusCode());
                    riskReason.setMessage("Response not successful. Status: " + response.getStatusCode());
                    log.error("文字审核失败 {}", "Response not successful. Status: " + response.getStatusCode());
                    return riskReason;
                }
            }
        } catch (Exception e) {

            e.printStackTrace();
            return riskReason;
        }
        return riskReason;
    }

    private static void dealScaleFile(File orginalFile, File file) throws IOException {
        Thumbnails.of(orginalFile)
                .scale(1f)
                .outputQuality(0.5f)
                .toFile(file);
    }

    @NotNull
    private static AliyunProperty getAliyunOssCip() {
      // AliyunProperty aliyunOssCip= new AliyunProperty();
      // aliyunOssCip.setAccount("xx");
      // aliyunOssCip.setAccessKeyId("LTAI5tEiUhEpp6iWSUaJBRTh");
      // aliyunOssCip.setAccessKeySecret("Bc5hGlLCz1jPEjBtx1Ct3DUVHLTqTU");
      // aliyunOssCip.setOssBucketName("mrhe-loadCookie-bucket-1");
      // aliyunOssCip.setCipRegionId("cn-shenzhen");
      // aliyunOssCip.setCipForeignEndpoint("xx");
      // aliyunOssCip.setCipChinaEndPoint("xx");
      // aliyunOssCip.setOssChinaEndPoint("xx");
      // return aliyunOssCip;
      return aliyunProperty;
    }




    /**
     * 创建请求客户端
     *
     * @param accessKeyId
     * @param accessKeySecret
     * @param endpoint
     * @return
     * @throws Exception
     */
    public static Client createClient(String accessKeyId, String accessKeySecret, String endpoint) throws Exception {
        Config config = new Config();
        config.setAccessKeyId(accessKeyId);
        config.setAccessKeySecret(accessKeySecret);
        // 设置http代理。
        //config.setHttpProxy("http://10.10.xx.xx:xxxx");
        // 设置https代理。
        //config.setHttpsProxy("https://10.10.xx.xx:xxxx");
        // 接入区域和地址请根据实际情况修改
        // 接入地址列表：https://help.aliyun.com/document_detail/467828.html?#section-uib-qkw-0c8
        config.setEndpoint(endpoint);
        return new Client(config);
    }

    public static ImageModerationResponse imageCheck(String imageUrl) throws Exception {
        AliyunProperty aliyunProperty = getAliyunOssCip();
        String accessKeySecret = aliyunProperty.getAccessKeySecret();
        String accessKeyId = aliyunProperty.getAccessKeyId();
        String endPoint = aliyunProperty.getCipChinaEndPoint();
        //注意，此处实例化的client请尽可能重复使用，避免重复建立连接，提升检测性能。
        Client client = createClient(accessKeyId, accessKeySecret, endPoint);

        // 创建RuntimeObject实例并设置运行参数
        RuntimeOptions runtime = new RuntimeOptions();

        // 检测参数构造。
        Map<String, String> serviceParameters = new HashMap<>();
        //公网可访问的URL。
        serviceParameters.put("imageUrl", imageUrl);
        //待检测数据唯一标识
        serviceParameters.put("dataId", UUID.randomUUID().toString());

        ImageModerationRequest request = new ImageModerationRequest();
        // 图片检测service：内容安全控制台图片增强版规则配置的serviceCode，示例：baselineCheck
        // 支持service请参考：https://help.aliyun.com/document_detail/467826.html?0#p-23b-o19-gff
        // baselineCheck aigcCheck
        request.setService("baselineCheck");
        request.setServiceParameters(JSON.toJSONString(serviceParameters));

        ImageModerationResponse response = null;
        try {
            response = client.imageModerationWithOptions(request, runtime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }

    public static void main(String[] args) throws Exception {
//
        // 上传文件到OSS
//        long start = System.currentTimeMillis();
//        File fileToUpload = new File("C:\\Users\\14550\\Pictures\\small.jpg");
//        String s = AliyunUtil.uploadOSSFile("loadCookie/loadCookie/loadCookie.png", fileToUpload,new Date(System.currentTimeMillis()+ DateUtils.WEK_DAY), "mrhe-ai-dev");
//        if (s != null) {
//            System.out.println("Upload successful::"+s);
//        } else {
//            System.out.println("Upload failed");
//        }
//        System.out.println("oss耗时: "+(System.currentTimeMillis()-start));
//        OSS ossClient = getOssClient();
//        List<String> list = Arrays.asList("mrhe-chatgpt-dev", "mrhe-loadCookie-bucket-1", "mrhetestbudect");
//        for (String bucketName : list) {
//            VoidResult voidResult = ossClient.deleteBucket(bucketName);
//            System.out.println("voidResult = " + voidResult);
//        }

//        // 下载文件
//        String downloadedContent = AliyunUtil.downloadOSSFile("example.txt");
//        System.out.println("Downloaded content:\n" + downloadedContent);
//
//        // 生成OSS预签名URL
//        String presignedURL = AliyunUtil.generatePresignedURL("example.txt", 3600 * 1000);
//        System.out.println("Presigned URL: " + presignedURL);

        // 文本审核
//        String contentToModerate = "裸体妹子";
//        RiskReason riskReason = AliyunUtil.textModeration(contentToModerate);
//        System.out.println("Moderation result:\n" + riskReason);
//        String loadCookie = "测试话术";
//        RiskReason testReason = AliyunUtil.textModeration(loadCookie);
//        System.out.println("Moderation result:\n" + testReason);

        /**
         * 阿里云账号AccessKey拥有所有API的访问权限，建议您使用RAM用户进行API访问或日常运维。
         * 常见获取环境变量方式：
         * 方式一：
         *     获取RAM用户AccessKey ID：System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
         *     获取RAM用户AccessKey Secret：System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
         * 方式二：
         *     获取RAM用户AccessKey ID：System.getProperty("ALIBABA_CLOUD_ACCESS_KEY_ID");
         *     获取RAM用户AccessKey Secret：System.getProperty("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
         */

        // 接入区域和地址请根据实际情况修改。
         doRealCheckImage(

                "https://mrhe-ai-test.oss-cn-shenzhen.aliyuncs.com/robot-image/W020171026258548340392.jpg?Expires=1709433712&OSSAccessKeyId=TMP.3KjjcNFPsNobG9W8oqPThxNeuvHgL3cbLMduphNe73kKHmmfPPeFvnFcFYkwvkExUxVcizAuR2MdUkTgu59fAQSmLnyEUv&Signature=TbkHkFdMVUb7M8s0h4qwCQYudIA%3D"
        );

    }



    public static ImageModerationResponseBody.ImageModerationResponseBodyDataResult doRealCheckImage(String imageUrl) throws Exception {
        ImageModerationResponse response = imageCheck(imageUrl);
        try {
            // 自动路由。
            if (response != null) {
                //区域切换到cn-beijing。
                if (500 == response.getStatusCode() || (response.getBody() != null && 500 == (response.getBody().getCode()))) {
                    // 接入区域和地址请根据实际情况修改。
                    response = imageCheck( imageUrl);
                }
            }
            // 打印检测结果。
            if (response != null) {
                if (response.getStatusCode() == 200) {
                    ImageModerationResponseBody body = response.getBody();
                    log.info("调用阿里云图片审核,返回参数body[{}]",JSONObject.toJSONString(body) );
                    if (body.getCode() == 200) {
                        ImageModerationResponseBody.ImageModerationResponseBodyData data = body.getData();

                        List<ImageModerationResponseBody.ImageModerationResponseBodyDataResult> results = data.getResult();
                        for (ImageModerationResponseBody.ImageModerationResponseBodyDataResult result : results) {
                            // nonLabel_lib
                            String label = result.getLabel();
                            //nonLabel
                            if (StringUtils.isNotBlank(label)
                                    &&! "nonLabel".equalsIgnoreCase(label)
                                    &&! "nonLabel_lib".equalsIgnoreCase(label)
                            ){
                                log.error("图片校验失败,图片返回结果为[{}]",JSONObject.toJSONString(result));
                                // 说明是 有问题的
                                return result;
                                        //AliyunImageCheck.getDescByName(label);
                            }
                        }
                    }
                } else {
                     log.error("图片审核失败,返回值为[{}]",response);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("图片审核失败,调用阿里云异常[{}]",e.getMessage());
        }
        return new ImageModerationResponseBody.ImageModerationResponseBodyDataResult();
    }

}

